const http = require('http')
const {v4:uuidv4}  = require("uuid")
const cors = require('cors')

/* 初始化server */
const express = require('express')
const app = express()
const server = http.createServer(app)
app.use(cors()) // 跨域
app.use(express.json());

/* 
    当前连接的用户
    id: {
        id: string,
        socket,
        nickname: string,
        avatar: string,
        roomId: string
    }
*/
const connectUsers = {}
/* 
    当前房间数据
    id: {
        id,
        hostUser: string,
        users: user[]
    }
*/
const rooms = {}

/* 根据roomId判断房间是否可加入，并返回房间信息 */
app.get('/room/canJoin/:roomId', (req, res) => {
    const roomId = req.params.roomId
    const room = rooms[roomId]

    if(room) {
        if(room.users.length >= 4) {
            res.status(500).json({
                success: false,
                data: null,
                message: '房间已满员'
            })
            return
        }
        res.send({
            success: true,
            data: room,
            message: '可以加入房间'
        })
    } else {
        res.status(500).json({
            success: false,
            data: null,
            message: '房间不存在'
        })
    }
})
/* 创建一个空房间 */
app.post('/room', (req, res) => {
    const { userId } = req.body
    const user = connectUsers[userId]

    if(!user) {
        res.status(500).json({
            success: false,
            data: null,
            message: '用户未连接'
        })
        return
    }

    const roomId = `2000-04-02-${Object.keys(rooms).length+1}`
    user.roomId = roomId
    rooms[roomId] = {
        id: roomId,
        hostUser: userId,
        users: []
    }
    console.log(`创建房间成功，当前房间数量: ${Object.keys(rooms).length}`)
    res.send({
        success: true,
        data: rooms[roomId],
        message: '创建房间成功'
    })
})
/* 根据userId修改昵称和头像 */
app.put('/user/:userId',(req, res) => {
    const { nickname, avatar } = req.body
    const userId = req.params.userId
    const user = connectUsers[userId]
    if(user) {
        user.nickname = nickname
        user.avatar = avatar
        res.json({
            success: true,
            data: null,
            message: '修改用户信息成功'
        })
    } else {
        res.status(500).json({
            success: false,
            data: null,
            message: '用户不存在'
        })
    }
})

/* socket.io */
const io = require('socket.io')(server, {
    cors: {
        origin: '*',
        methods: ["GET", "POST"]
    }
})
io.on('connection',(socket) => {
    createNewUser(socket)

    socket.on('disconnect', () => {
        userDisconnect(socket)
    })
    socket.on('join-room', (data) => {
        joinRoom(data,socket)
    })
    socket.on('connect-signal', (data) => {
        connectSignal(data,socket)
    })
    socket.on('connect-init', (data) => {
        connectInit(data,socket)
    })
})

/**
 * 创建一个新的用户
 */
const createNewUser = (socket) => {
    const user = {
        id: socket.id,
        nickname: '',
        avatar: '',
        roomId: '',
        streamId: Date.now()
    }
    connectUsers[socket.id] = user
    console.log(`新的socket连接,${socket.id}, 当前连接用户数量: ${Object.keys(connectUsers).length}` );
}
/**
 * 用户断开socket, 从connectUsers中删除，同时从rooms中删除
 */
const userDisconnect = (socket) => {
    userLeaveRoom(socket.id)
    delete connectUsers[socket.id]
    console.log(`关闭连接:${socket.id}, 当前连接用户数量: ${Object.keys(connectUsers).length}`);
}
/**
 * 用户退出房间
 */
const userLeaveRoom = (userId) => {
    const user = connectUsers[userId]
    if(user && user.roomId) {
        const room = rooms[user.roomId]
        if(!room) {
            return false
        }
        const index = room.users.findIndex(user => user.id === userId)
        room.users.splice(index, 1)
        io.to(room.id).emit("room-update", room)
        console.log(`成员离开，当前人数为:${room.users.length}`);
        /* 如果用户为0，清掉房间 */
        setTimeout(() => {
            if(room.users.length === 0) {
                delete rooms[user.roomId]
                console.log("关闭一个房间，当前房间数量", Object.keys(rooms).length);  
            }
        }, 5000);
        return true
    } else {
        return false
    }
}
/**
 * 加入房间
 */
const joinRoom = ({ userId, roomId },socket) => {
    const user = connectUsers[userId]
    const room = rooms[roomId]
    if(!user || !room) {
        return
    }

    /* 添加一个成员到房间里, 加一个前置校验，如果已经存在了则不需要重复加入 */
    const hasInRoom = room.users.find(user => user.id === userId)
    if(!hasInRoom) {
        socket.join(roomId)

        user.roomId = roomId
        room.users.push(user)
        console.log(`新成员加入房间，人数为: ${room.users.length}`);

        /* 告知其他用户进行对等连接 */
        room.users.forEach(user => {
            if(user.id !== userId) {
                /* 向单个用户请求和自己连接 */
                io.to(user.id).emit("connect-prepare", {
                    connectUserId: userId
                })
            }
        })

        /* 通知room-update */
        io.to(roomId).emit("room-update", room)
    }
}
/**
 * 交换信令
 */
const connectSignal = (data, socket) => {
    const { connectUserId, signal } = data
    const signalingData = {
        signal,
        connectUserId: socket.id, // 自身的id
    }
    /* 向发起方请求连接 */
    io.to(connectUserId).emit('connect-signal', signalingData)
}
/**
 * 初始化webRTC连接
 */
const connectInit = (data, socket) => {
    const { connectUserId } = data
    const initData = {
        connectUserId: socket.id,
    }
    io.to(connectUserId).emit('connect-init', initData)
}

/* 启动监听 */
const PORT  = process.env.PORT || 8201

server.listen(PORT, () => {
    console.log(`server is running in ${PORT}`)
})

